package com.example.design_pattern.strategy;

// 本案例演示的是策略设计模式


// 定义策略接口
interface Strategy {
    // 里面定义了一个抽象方法。看字面意思就是，做一些操作，这个名字取的非常宽泛。至于具体做什么操作呢，不确定。
    int doOperation(int num1, int num2);
}

// 实现加法策略
// 加法策略是一个类。这个类实现了doOperation方法，具体里面是做减法逻辑。
class AddStrategy implements Strategy {
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }
}

// 实现减法策略
// 减法策略整个是一个类。里面实现了doOperation方法，具体在里面做减法逻辑。
class SubtractStrategy implements Strategy {
    public int doOperation(int num1, int num2) {
        return num1 - num2;
    }
}


// 如果还有实现别的算法的话，直接新建一个策略类，然后实现doOperation方法就好了。
// 使用这个策略类里面的具体方法的逻辑的话，就新建一个上下文对象，新建上下文对象的时候，把新的策略对象给它就可以。

// 上下文类，用于维护当前使用的策略
// 上下文类是干嘛的呢？
class Context {
    // 装状态的地方，存放当前上下文中使用的策略
    private Strategy strategy;

    // 构造函数
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public int executeStrategy(int num1, int num2) {
        return strategy.doOperation(num1, num2);
    }
}

public class StrategyTest {
    public static void main(String[] args) {
        // 创建上下文对象，并指定加法策略。
        // 就是把自己想使用的具体的策略，给上下文的构造函数。这样，就把这个策略保存在上下文对象里面了。
        Context context = new Context(new AddStrategy());
        // 到时候要做加法的话，就直接从上下文对象里面直接点出执行策略的那个方法来执行。
        System.out.println("10 + 5 = " + context.executeStrategy(10, 5));

        // 切换为减法策略
        // 如果想要切换，就是重新给context对象赋值而已。重新赋值覆盖，就是切换了。
        context = new Context(new SubtractStrategy());
        System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
    }
}


// 备注：
// 策略设计模式用于定义一系列算法，将每个算法封装在独立的类中，并使它们可以互相替换。
// 在这个示例中，Strategy接口定义了一个算法的操作，然后我们有两个具体的策略类：AddStrategy和SubtractStrategy，分别实现了加法和减法操作。
// Context类用于维护当前使用的策略，并且根据当前的策略执行相应的操作。
// 在Main类中，我们可以轻松地切换不同的策略，而不用修改现有的代码。

// 策略模式一般适用于什么场景
// 策略模式适用于需要根据不同情况采用不同算法或策略的场景，具体包括但不限于以下情况：
//1. **算法多样性**：当一个系统中包含多个类似的算法，但每种算法在某些方面有所不同，并且需要在运行时根据情况选择不同的算法时，可以使用策略模式。
//2. **避免条件语句**：策略模式可以帮助避免使用大量的条件语句来选择算法，使代码更加清晰、简洁，并且易于维护和扩展。
//3. **可扩展性**：通过定义一系列的策略类，系统可以灵活地添加新的算法，而不需要修改现有的代码。
//4. **开闭原则**：策略模式符合开闭原则，即对扩展开放、对修改关闭，可以在不修改现有代码的情况下添加新的算法。
//5. **单一职责原则**：策略模式将每种算法封装在独立的策略类中，使每个类负责一种算法，符合单一职责原则。
//总之，策略模式适用于需要在运行时动态选择算法，并且需要将算法与使用算法的客户端代码分离的情况。

// 个人备注：其实，设计模式并非是一种必须的选项，它只是一种将代码组织的更加有条理、使用起来更加简便、更加语义化、封装性更好、扩展性更好的组织套路而已。
// 如果不用设计模式组织，以我们最直观的思维，那能达到要求，其实也可以达到要求。
// 以本设计模式为例的话，其实，核心的逻辑也就是一个加法、一个减法而已。我可以把加法、减法的方法定义在随便什么地方。比如定义在一个类里面，定义成不同的局部方法等等，没必要一定要Strategy类的实现类这样包装。
// 至于自己按照自己的直觉或者喜好，随便将这种不同的算法放在随便什么地方，只要能调用到好就可以。这样放的话，和策略模式，是否会在封装性、扩展性、语义化方面有差别，那后续再研究。
